#include "GeneticAlgorithm.hpp"
#define DATASIZE 100
__managed__ float Dataset[100][3]=
{{1,171.5487975,60.21838701},
{0,162.9471637,54.3567427},
{1,168.9573047,56.79476735},
{0,156.2632499,40.38446824},
{0,157.4300811,41.77733535},
{0,158.2294602,39.1437104},
{1,183.6437053,80.33798698},
{0,169.3002723,60.93761101},
{0,163.8091725,52.84436505},
{1,166.6262008,63.15164509},
{0,162.126861,58.74057745},
{1,170.4050503,68.77771804},
{1,164.38062,57.2469079},
{1,160.4666524,47.1551415},
{1,178.0083355,73.11916594},
{0,159.3252576,47.80959171},
{1,162.3171854,61.17646904},
{1,172.1970693,62.94554003},
{1,153.8331299,52.56440629},
{0,169.0753163,64.61222188},
{0,169.5381438,57.48308633},
{0,159.6789787,52.92995302},
{0,150.3563686,36.20289583},
{0,171.1619218,62.60958488},
{0,163.386587,46.86561276},
{1,170.9421897,63.9986105},
{0,152.2782825,46.30879398},
{0,163.5719073,52.30308899},
{0,173.4991203,60.39974322},
{0,154.7363173,42.10381483},
{1,172.8242912,66.65106828},
{1,168.0960265,65.30509913},
{1,174.33205,71.42144949},
{0,167.9319539,66.83684809},
{0,153.9296915,48.940441},
{1,167.4270381,66.09050738},
{1,174.2279534,69.0004324},
{1,167.6223859,68.64861671},
{0,169.1942017,48.07745781},
{0,164.5858332,50.21708379},
{1,170.7012493,69.46834073},
{0,162.8143619,52.25975429},
{0,163.2758257,62.13592017},
{0,162.6980713,48.87548577},
{1,162.4598346,54.98677621},
{1,179.8979894,73.13481588},
{1,165.8146459,58.05928605},
{1,180.298673,77.47732791},
{0,164.8029306,49.33510862},
{0,146.9286648,35.79915041},
{1,172.2548837,66.82581833},
{1,176.1845745,70.81177155},
{1,171.9000694,68.39598839},
{1,168.1993307,66.97615954},
{0,156.2959102,48.85013322},
{0,173.3494767,67.04850649},
{1,173.8671601,82.36327595},
{0,161.0326971,49.03958656},
{0,152.6380025,44.51706885},
{1,178.8132443,65.22187073},
{1,172.442098,65.88385532},
{0,172.0392911,57.41900135},
{0,156.7306098,46.63332452},
{0,167.9518415,65.34697002},
{0,176.4417237,66.29084072},
{1,163.5205543,65.64383514},
{1,175.8553477,67.80855135},
{1,175.010102,75.9385863},
{0,171.7618214,69.73609492},
{1,163.2606002,59.40222194},
{1,168.6066991,72.23958503},
{0,159.39705,45.09171731},
{1,186.7890745,87.45189312},
{1,170.6977211,64.07202345},
{1,168.9354334,67.78119634},
{1,163.7297925,75.68833893},
{0,161.0649964,50.55694834},
{1,172.5060981,72.60554452},
{1,155.1443577,53.40404563},
{1,177.8884226,75.44856644},
{1,158.2835448,63.0293289},
{1,170.4020754,65.66339975},
{1,181.18978,82.73084289},
{1,171.9982662,67.37235866},
{1,175.8616495,61.7784235},
{1,164.8616351,65.21009053},
{0,165.8449531,58.30889379},
{0,162.7879619,59.19233832},
{1,171.5449207,70.55004526},
{1,179.4186743,73.97174195},
{0,163.4578204,57.75339103},
{0,162.9953316,39.52024044},
{1,183.4131309,76.40512819},
{1,173.4853449,64.20463134},
{0,169.957249,63.1710442},
{1,176.1586968,72.76483028},
{1,180.0059993,78.9113166},
{1,173.7178829,68.49978487},
{1,161.7586877,57.50210824},
{1,162.1086246,59.82980718}};
template<>//特化染色体的初始化操作
__device__ void Chromosome<float>::initial(){
    unsigned int tid= blockIdx.x * blockDim.x + threadIdx.x;//线程编号
    curandState_t state;
    curand_init(clock(),tid,0,&state);
    for(unsigned int i=0; i<this->lengthOfGenes;i++){
        this->genes[i]=curand(&state)%100;
    }
}
template<>//特化染色体的交叉操作
__device__ void Chromosome<float>::crossover(Chromosome *c){
    this->genes[1] = c->genes[1];
}
template<>//特化染色体的变异操作
__device__ void Chromosome<float>::mutation(){
    
    unsigned int tid= blockIdx.x * blockDim.x + threadIdx.x;//线程编号
    curandState_t state;
    curand_init(clock(),tid,0,&state);//初始化随机数生成器
    for (unsigned int i = 0; i < this->lengthOfGenes; i++) {
        this->genes[i] = this->genes[i]+(curand_uniform(&state)-0.5)*10;
    }
}

//定义染色体的适应度函数
__global__ void get_fitness(Population<float>* p){
    unsigned int tid= blockIdx.x * blockDim.x + threadIdx.x;//线程编号
    float sum=0,temp=0;
    if(tid<p->numOfIndiv){
        for (unsigned int i = 0; i < DATASIZE;i++)
        {
            temp=p->individuals[tid]->genes[0]+ p->individuals[tid]->genes[1]*Dataset[i][1]+p->individuals[tid]->genes[2]*Dataset[i][2];
            if(temp>0) temp=1;
            else temp=0;
            sum-=powf(Dataset[i][0]-temp,2);
        }
        sum-=0.01*powf(p->individuals[tid]->genes[0],2)+0.01*powf(p->individuals[tid]->genes[1],2)+0.01*powf(p->individuals[tid]->genes[2],2);
        p->individuals[tid]->fitness=sum;
    }
}

template<>//特化评估函数,评估种群中每个个体的适应度
void pop_evaluate(Population<float> *p,unsigned int numIndiv){
    get_fitness<<<(numIndiv+BLOCK_SIZE-1)/BLOCK_SIZE,BLOCK_SIZE>>>(p);
}
__host__ void cpu_test(Chromosome<float>* best){
    float sum=0,temp=0;
    for(unsigned int i = 0; i < DATASIZE;i++){
        temp=best->genes[0]+ best->genes[1]*Dataset[i][1]+best->genes[2]*Dataset[i][2];
        if(temp>0){
            temp=1;
        }
        else temp=0;
        sum+=fabs(Dataset[i][0]-temp);
    }
    printf("误分类次数=%d次\n",(int)sum);
}
int main(int argc, char const *argv[])
{
    Chromosome<float> best(3);
    printf("hello!Genetic Algorithm begin!\n");
    GA<float>(&best,1024,3,0.8,0.5,0.5,-18,200);
    printf("Best genes are o(%f+%f*x1+%f*x2)\tMaxFitness=%f\n",best.genes[0],best.genes[1],best.genes[2],best.fitness);
    cpu_test(&best);
    return 0;
}
